package gorm

import (
	"errors"
	"time"

	"codeup.aliyun.com/613d4e14109ccab1ac5911f8/golang/base/database/gorm/opentracing"
	"github.com/asim/go-micro/v3/config"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func NewDbProvider(config config.Config) (*gorm.DB, error) {
	driver := config.Get("db", "driver").String("mysql")
	connectionString := config.Get("db", "connection_string").String("")

	if len(driver) == 0 {
		return nil, errors.New("driver is empty")
	}

	if len(connectionString) == 0 {
		return nil, errors.New("connection_string is empty")
	}
	db, err := gorm.Open(mysql.Open(connectionString), &gorm.Config{})
	if err != nil {
		return nil, err
	}
	db.Debug()

	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}

	sqlDB.SetMaxIdleConns(10)

	// SetMaxOpenConns sets the maximum number of open connections to the database.
	sqlDB.SetMaxOpenConns(100)

	// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
	sqlDB.SetConnMaxLifetime(3 * time.Minute)

	// addAutoCallbacks(db)

	opentracing.AddGormCallbacks(db)

	return db, nil
}

// func addAutoCallbacks(db *gorm.DB) {
// 	// 替换替换默认的钩子
// 	db.Callback().Create().Replace("gorm:update_time_stamp", updateTimeForCreateCallback)
// 	db.Callback().Update().Replace("gorm:update_time_stamp", updateTimeForUpdateCallback)
// }

// func updateTimeForCreateCallback(db *gorm.DB) {
// 	if db.Error == nil {
// 		if db.Statement.Schema != nil && !db.Statement.Unscoped {
// 			for _, c := range db.Statement.Schema.UpdateClauses {
// 				db.Statement.AddClause(c)
// 			}
// 		}
// 		if db.Statement.SQL.String() == "" {
// 			db.Statement.SQL.Grow(180)
// 			db.Statement.AddClauseIfNotExists(clause.Update{})
// 			if set := ConvertToAssignments(db.Statement); len(set) != 0 {
// 				db.Statement.AddClause(set)
// 			} else {
// 				return
// 			}
// 			db.Statement.Build("UPDATE", "SET", "WHERE")
// 		}

// 		if _, ok := db.Statement.Clauses["WHERE"]; !db.AllowGlobalUpdate && !ok {
// 			db.AddError(gorm.ErrMissingWhereClause)
// 			return
// 		}

// 		if !db.DryRun && db.Error == nil {
// 			result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)

// 			if err == nil {
// 				db.RowsAffected, _ = result.RowsAffected()
// 			} else {
// 				db.AddError(err)
// 			}
// 		}
// 	}
// 	if !scope.HasError() {
// 		nowTime := time.Now()

// 		// 通过 scope.Fields() 获取所有字段，判断当前是否包含所需字段
// 		if createTimeField, ok := scope.FieldByName("Ctime"); ok {
// 			if createTimeField.IsBlank { // 可判断该字段的值是否为空
// 				createTimeField.Set(nowTime)
// 			}
// 		}

// 		if modifyTimeField, ok := scope.FieldByName("Mtime"); ok {
// 			if modifyTimeField.IsBlank {
// 				modifyTimeField.Set(nowTime)
// 			}
// 		}
// 	}
// }

// func updateTimeForUpdateCallback(db *gorm.DB) {
// 	// scope.Get(...) 根据入参获取设置了字面值的参数，例如本文中是 gorm:update_column ，它会去查找含这个字面值的字段属性
// 	if _, ok := scope.Get("gorm:mtime"); !ok {
// 		// scope.SetColumn(...) 假设没有指定 update_column 的字段，我们默认在更新回调设置 ModifiedOn 的值
// 		scope.SetColumn("mtime", time.Now())
// 	}
// }
